home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
video
/
fly8111-.000
/
fly8111-
/
fly8
/
COMMON
/
vgr.c
< prev
next >
Wrap
C/C++ Source or Header
|
1979-12-31
|
7KB
|
375 lines
/* --------------------------------- vgr.c ---------------------------------- */
/* This is part of the flight simulator 'fly8'.
* Author: Eyal Lebedinsky (eyal@ise.canberra.edu.au).
*/
/* drawing primitives for a banked video system (like VGA).
*/
#include "fly.h"
#include "vgr.h"
#define BANK_FIX(va,vb) \
if ((Uint)((va)^(vb)) >= 0xc000U) { \
va &= 0x0ffffU; \
if ((va) >= 0xc000U) \
vSetBank (--vBank); \
else if ((va) < 0x4000U) \
vSetBank (++vBank); \
}
#define SET_PIXEL(va,c) \
if (T_MSET == vWriteMode) \
vMem[va] = (Uchar)(c); \
else if (T_MOR == vWriteMode) \
vMem[va] |= (c); \
else \
vMem[va] ^= (c)
static Uchar FAR *vMem = NULL;
static Uint vWidth = 0, vHeight = 0, vXBytes = 0;
static void (FAR *vSetBank) (int bank) = NULL;
static int (FAR *vSetBase) (Ulong base) = NULL;
static Ulong vActiveBase = 0;
static int vBank = 0;
static int vWriteMode = T_MSET;
static Uint x1 = 0, y1 = 0, pva = 0, xydone = 0;
#ifdef USE_DIVTAB
static Uint FAR vDivTab[2048] = {0};
#endif
extern int FAR
vSetWriteMode (int mode)
{
vWriteMode = mode;
return (0);
}
extern int FAR
vSetActive (int page)
{
vActiveBase = page * (Ulong)vXBytes * (Ulong)vHeight;
xydone = 0;
return (0);
}
extern int FAR
vSetVisual (int page) /* Set visual address */
{
if (vSetBase)
return (vSetBase (page * (Ulong)vXBytes * (Ulong)vHeight));
else
return (1);
}
extern int FAR
vSetMem (Uchar *vmem)
{
vMem = vmem;
vActiveBase = 0;
return (0);
}
extern int FAR
vSetSize (Uint width, Uint height, Uint xbytes)
{
vWidth = width;
vHeight = height;
vXBytes = xbytes;
return (0);
}
extern void FAR
vInit (Uchar *vmem, Uint width, Uint height, Uint xbytes,
void (FAR *setbank) (int page),
int (FAR *setbase) (Ulong base))
{
vMem = vmem;
vWidth = width;
vHeight = height;
vXBytes = xbytes;
vSetBank = setbank;
vSetBase = setbase;
vSetWriteMode (T_MSET);
vSetActive (0);
vSetVisual (0);
#ifdef USE_DIVTAB
{
int i;
vDivTab[0] = 0L;
for (i = 1; i < rangeof (vDivTab); ++i)
vDivTab[i] = (Uint)(0x00010000UL / i);
}
#endif
}
/* This does pure C drawing.
*/
INLINED static Uint NEAR
vILoop (Uint va, Uint dy, Uint dx, int dvx, int dvy, int c)
{
int err; /* conceptualy */
int count;
Uint vb;
/* dx > dy never =!!!
* dx > 0
* dy >= 0
*
* set:
* dy = (dy*0x10000)/dx
* dx = 0x10000
*/
count = dx;
err = dx >> 1;
if (T_MSET == vWriteMode) {
while (--count >= 0) {
vb = va;
va += dvx;
if ((err -= dy) < 0) {
err += dx;
va += dvy;
}
BANK_FIX (va, vb);
vMem[va] = (Uchar)c;
}
} else if (T_MOR == vWriteMode) {
while (--count >= 0) {
vb = va;
va += dvx;
if ((err -= dy) < 0) {
err += dx;
va += dvy;
}
BANK_FIX (va, vb);
vMem[va] |= c;
}
} else {
while (--count >= 0) {
vb = va;
va += dvx;
if ((err -= dy) < 0) {
err += dx;
va += dvy;
}
BANK_FIX (va, vb);
vMem[va] ^= c;
}
}
return (va);
}
INLINED static Uint NEAR
vSLoop (Uint va, int count, int sv, int c)
{
Uint vb;
if (T_MSET == vWriteMode) {
while (--count >= 0) {
vb = va;
va += sv;
BANK_FIX (va, vb);
vMem[va] = (Uchar)c;
}
} else if (T_MOR == vWriteMode) {
while (--count >= 0) {
vb = va;
va += sv;
BANK_FIX (va, vb);
vMem[va] |= c;
}
} else {
while (--count >= 0) {
vb = va;
va += sv;
BANK_FIX (va, vb);
vMem[va] ^= c;
}
}
return (va);
}
INLINED static Uint NEAR
vGrAddr (Uint x, Uint y)
{
Ulong xy;
int bank;
bank = (int)((xy = x + vActiveBase + y*(Ulong)vXBytes) >> 16);
if (bank != vBank)
vSetBank (vBank = bank);
return (0x0ffffU & (Uint)xy);
}
extern void FAR
vMoveTo (Uint x, Uint y)
{
#if DEBUG_VGR
if (x >= vWidth)
x = vWidth-1;
if (y >= vHeight)
y = vHeight-1;
#endif
x1 = x;
y1 = y;
xydone = 0;
}
extern void FAR
vDrawTo (Uint x2, Uint y2, Uint c)
{
int dx, dy, svx, svy;
int t;
#if DEBUG_VGR
if (x2 >= vWidth)
x2 = vWidth-1;
if (y2 >= vHeight)
y2 = vHeight-1;
#endif
t = 0;
if (!xydone) {
t = 1;
xydone = 1;
pva = vGrAddr (x1, y1);
SET_PIXEL (pva, c);
}
svx = 1;
if ((dx = x2 - x1) < 0) {
dx = -dx;
svx = -1;
}
svy = vXBytes;
if ((dy = y2 - y1) < 0) {
dy = -dy;
svy = -svy;
}
if (dx > dy) {
if (0 == dy) {
Uint vb;
vb = pva + x2 - x1; /* end point */
if (!((Uint)((pva)^(vb)) >= 0xc000U &&
(vb >= 0xc000U || vb < 0x4000U))
&& (T_MSET == vWriteMode)
) {
memset (vMem + (svx>0 ? pva+1 : vb), c, dx);
pva = vb;
} else
pva = vSLoop (pva, dx, svx, c);
} else
pva = vILoop (pva, dy, dx, svx, svy, c);
++GrStats[dx+t];
} else if (dx < dy) {
if (0 == dx)
pva = vSLoop (pva, dy, svy, c);
else
pva = vILoop (pva, dx, dy, svy, svx, c);
++GrStats[dy+t];
} else /* if (dx == dy) */ {
if (dx)
pva = vSLoop (pva, dx, svx+svy, c);
++GrStats[dx+t];
}
x1 = x2;
y1 = y2;
}
/* Based on the acm version from TOG V11N3 (July 1992), this one is
* modified to do 2 quads at a time to limit VGA bank flips.
*/
#define POINT(x,y,c) \
do { \
if (xy = xxyy+(x)+(y), (int)(xy>>16) != vBank) \
vSetBank (vBank = (int)(xy>>16)); \
va = 0x0ffffU & (Uint)xy; \
SET_PIXEL (va, c); \
} while (0)
#define INCX() \
(x++, b2x += b2, dxt += d2xt, t += dxt)
#define INCY() \
(y--, a2y -= a2, dyt += d2yt, t += dyt, yy -= vXBytes)
extern void FAR
vEllipse (Uint xc, Uint yc, Uint a, Uint b, Uint c)
{
long xxyy;
Ulong xy;
Uint va = 0;
int x = 0, y = b;
long yy = y*(long)vXBytes;
long a2 = (long)a*a, b2 = (long)b*b;
long crit1 = -(a2/4 + a%2 + b2);
long crit2 = -(b2/4 + b%2 + a2);
long crit3 = -(b2/4 + b%2);
long t = -a2*y;
long dxt = 2*b2*x, dyt = -2*a2*y;
long d2xt = 2*b2, d2yt = 2*a2;
long b2x = b2*x, a2y = a2*y;
if (xc < a || xc+a >= vWidth ||
yc < b || yc+b >= vHeight)
return;
xxyy = xc + vActiveBase + yc * (long)vXBytes;
while (y >= 0 && x <= (int)a) {
POINT (x, yy, c);
if (x && y)
POINT (-x, yy, c);
if (t + b2x <= crit1 || t + a2y <= crit3)
INCX ();
else if (t - a2y > crit2)
INCY ();
else {
INCX ();
INCY ();
}
}
x = 0, y = b;
yy = y*(long)vXBytes;
t = -a2*y;
dxt = 2*b2*x, dyt = -2*a2*y;
d2xt = 2*b2, d2yt = 2*a2;
b2x = b2*x, a2y = a2*y;
while (y >= 0 && x <= (int)a) {
if (x || y)
POINT (-x, -yy, c);
if (x && y)
POINT ( x, -yy, c);
if (t + b2x <= crit1 || t + a2y <= crit3)
INCX ();
else if (t - a2y > crit2)
INCY ();
else {
INCX ();
INCY ();
}
}
}
#undef BANK_FIX
#undef SET_PIXEL
#undef POINT
#undef INCX
#undef INCY